package com.cts.rt.model;

import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.xml.bind.annotation.XmlTransient;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements UserDetails {

	private static final long serialVersionUID = -508873257128094299L;

	public static enum EmployeeType {
		Employee, Contractor
	}

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID")
	private Long id;

	@Column(name = "EMPLOYEE_ID")
	private String employeeId;

	@Version
	@Column(name = "VERSION")
	private Integer version;

	@Column(name = "PASSWORD", nullable = false, length = 128)
	private String password;

	@Transient
	private String confirmPassword;

	@Column(name = "PASSWORD_HINT")
	private String passwordHint;

	@Column(name = "FIRST_NAME")
	private String firstName;

	@Column(name = "LAST_NAME")
	private String lastName;

	@OneToMany(mappedBy = "employee")
	private List<EmployeeAddress> addresses;

	@Column(name = "EMAIL", nullable = false)
	private String email;

	@OneToMany(mappedBy = "employee")
	private List<EmployeePhone> phone;

	@Enumerated(EnumType.STRING)
	@Column(name = "RESOURCE_TYPE")
	private EmployeeType resourceType;

	@ManyToOne
	@JoinColumn(name = "GROUP_ID")
	private EmployeeGroup employeeGroup;

	@Temporal(TemporalType.DATE)
	@Column(name = "DATE_OF_JOIN", nullable = false, updatable = false)
	private Date dateOfJoin;

	@Column(name = "ACTIVE", nullable = false)
	private boolean isActive;

	@Column(name = "IS_EMPLOYEE", nullable = false)
	private boolean isEmployee;

	@ManyToOne
	@JoinColumn(name = "LEVEL_ID", nullable = false)
	private EmployeeLevel employeeLevel;

	@Column(name = "ACCOUNT_EXPIRED", nullable = false)
	private boolean accountExpired = true;

	@Column(name = "ACCOUNT_LOCKED")
	private boolean accountLocked = true;

	@Column(name = "CREDENTIALS_EXPIRED", nullable = false)
	private boolean credentialsExpired = true;

	@Override
	public Set<GrantedAuthority> getAuthorities() {
		Set<GrantedAuthority> authorities = new LinkedHashSet<GrantedAuthority>();
		authorities.add(employeeLevel);
		return authorities;
	}

	@Override
	public String getPassword() {
		return password;
	}

	@Override
	public String getUsername() {
		return employeeId;
	}

	public boolean isAccountExpired() {
		return accountExpired;
	}

	public boolean isAccountLocked() {
		return accountLocked;
	}

	public boolean isCredentialsExpired() {
		return credentialsExpired;
	}

	public void setAccountExpired(boolean accountExpired) {
		this.accountExpired = accountExpired;
	}

	public void setAccountLocked(boolean accountLocked) {
		this.accountLocked = accountLocked;
	}

	public void setCredentialsExpired(boolean credentialsExpired) {
		this.credentialsExpired = credentialsExpired;
	}

	@Override
	public boolean isEnabled() {
		return isActive;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@XmlTransient
	public List<EmployeeAddress> getAddresses() {
		return addresses;
	}

	public void setAddresses(List<EmployeeAddress> addresses) {
		this.addresses = addresses;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@XmlTransient
	public List<EmployeePhone> getPhone() {
		return phone;
	}

	public void setPhone(List<EmployeePhone> phone) {
		this.phone = phone;
	}

	public EmployeeType getResourceType() {
		return resourceType;
	}

	public void setResourceType(EmployeeType resourceType) {
		this.resourceType = resourceType;
	}

	public Date getDateOfJoin() {
		return dateOfJoin;
	}

	public void setDateOfJoin(Date dateOfJoin) {
		this.dateOfJoin = dateOfJoin;
	}

	public boolean isActive() {
		return isActive;
	}

	public void setActive(boolean isActive) {
		this.isActive = isActive;
	}

	public boolean isEmployee() {
		return isEmployee;
	}

	public void setEmployee(boolean isEmployee) {
		this.isEmployee = isEmployee;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public EmployeeLevel getEmployeeLevel() {
		return employeeLevel;
	}

	public void setEmployeeLevel(EmployeeLevel employeeLevel) {
		this.employeeLevel = employeeLevel;
	}

	public Integer getVersion() {
		return version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public String getConfirmPassword() {
		return confirmPassword;
	}

	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	public String getPasswordHint() {
		return passwordHint;
	}

	public void setPasswordHint(String passwordHint) {
		this.passwordHint = passwordHint;
	}

	public String getFullName() {
		return firstName + ' ' + lastName;
	}

	@Override
	public boolean isAccountNonExpired() {
		return !accountExpired;
	}

	@Override
	public boolean isAccountNonLocked() {
		return !accountLocked;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return !credentialsExpired;
	}

	public String getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(String employeeId) {
		this.employeeId = employeeId;
	}

	public EmployeeGroup getEmployeeGroup() {
		return employeeGroup;
	}

	public void setEmployeeGroup(EmployeeGroup employeeGroup) {
		this.employeeGroup = employeeGroup;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Employee [id=");
		builder.append(id);
		builder.append(", employeeId=");
		builder.append(employeeId);
		builder.append(", version=");
		builder.append(version);
		builder.append(", password=");
		builder.append(password);
		builder.append(", confirmPassword=");
		builder.append(confirmPassword);
		builder.append(", passwordHint=");
		builder.append(passwordHint);
		builder.append(", firstName=");
		builder.append(firstName);
		builder.append(", lastName=");
		builder.append(lastName);
		builder.append(", addresses=");
		builder.append(addresses);
		builder.append(", email=");
		builder.append(email);
		builder.append(", phone=");
		builder.append(phone);
		builder.append(", resourceType=");
		builder.append(resourceType);
		builder.append(", employeeGroup=");
		builder.append(employeeGroup);
		builder.append(", dateOfJoin=");
		builder.append(dateOfJoin);
		builder.append(", isActive=");
		builder.append(isActive);
		builder.append(", isEmployee=");
		builder.append(isEmployee);
		builder.append(", employeeLevel=");
		builder.append(employeeLevel);
		builder.append(", accountExpired=");
		builder.append(accountExpired);
		builder.append(", accountLocked=");
		builder.append(accountLocked);
		builder.append(", credentialsExpired=");
		builder.append(credentialsExpired);
		builder.append("]");
		return builder.toString();
	}

}
